package model

import (
	"context"
	"database/sql"
	"fmt"
	"time"

	"github.com/Masterminds/squirrel"
	"github.com/zeromicro/go-zero/core/stores/cache"
	"github.com/zeromicro/go-zero/core/stores/sqlc"
	"github.com/zeromicro/go-zero/core/stores/sqlx"
)

var _ UserModel = (*customUserModel)(nil)

type (
	// UserModel is an interface to be customized, add more methods here,
	// and implement the added methods in customUserModel.
	UserModel interface {
		userModel
		RowBuilder() squirrel.SelectBuilder
		Truncate(ctx context.Context)
		FindAllEx(Current int64, PageSize int64) (*[]UserList, error)
		Count() (int64, error)
	}

	UserList struct {
		Id           int64          `db:"id"`
		Phone        sql.NullString `db:"phone"`        // 电话
		Gender       sql.NullString `db:"gender"`       // 性别 F,M,N
		Nickname     sql.NullString `db:"nickname"`     // 昵称
		Avatar       sql.NullString `db:"avatar"`       // 头像
		Password     sql.NullString `db:"password"`     // 密码
		Isderegister int64          `db:"isderegister"` // 是否注销
		Uid          sql.NullString `db:"uid"`          // 用户ID
		Invcode      sql.NullString `db:"invcode"`      // 邀请码
		Wxunionid    sql.NullString `db:"wxunionid"`    // 微信unionid
		Wxopenid     sql.NullString `db:"wxopenid"`     // 微信Openid
		Name         sql.NullString `db:"name"`         // 用户名
		CreateTime   time.Time      `db:"create_time"`
		UpdateTime   time.Time      `db:"update_time"`
	}

	customUserModel struct {
		*defaultUserModel
	}
)

// NewUserModel returns a model for the database table.
func NewUserModel(conn sqlx.SqlConn, c cache.CacheConf) UserModel {
	return &customUserModel{
		defaultUserModel: newUserModel(conn, c),
	}
}

func (m *defaultUserModel) RowBuilder() squirrel.SelectBuilder {
	return squirrel.Select(userRows).From(m.table)
}

func (m defaultUserModel) Truncate(ctx context.Context) {
	build := m.RowBuilder()
	query, values, err := build.ToSql()
	if err == nil {
		var resp []*User
		err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...)
		if err == nil {
			for _, r := range resp {
				m.Delete(ctx, r.Id)
			}
			m.ExecNoCacheCtx(ctx, fmt.Sprintf("TRUNCATE %s  ", m.tableName()))
		}
	}
}

func (m *defaultUserModel) FindAllEx(Current int64, PageSize int64) (*[]UserList, error) {

	//query := fmt.Sprintf("select %s from %s limit ?,?", sysUserRows, m.table)
	query := "select * from user  limit ?,?"
	var resp []UserList
	err := m.CachedConn.QueryRowsNoCache(&resp, query, (Current-1)*PageSize, PageSize)
	switch err {
	case nil:
		return &resp, nil
	case sqlc.ErrNotFound:
		return nil, ErrNotFound
	default:
		return nil, err
	}
}

func (m *defaultUserModel) Count() (int64, error) {
	query := fmt.Sprintf("select count(*) as count from %s", m.table)

	var count int64
	err := m.CachedConn.QueryRowNoCache(&count, query)

	switch err {
	case nil:
		return count, nil
	case sqlc.ErrNotFound:
		return 0, ErrNotFound
	default:
		return 0, err
	}
}
